package org.xyf.workflow.service.impl;

import org.flowable.engine.*;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.idm.api.Group;
import org.flowable.idm.api.User;
import org.flowable.task.api.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.xyf.workflow.config.FlowableConfig;
import org.xyf.workflow.service.WorkflowService;

import java.sql.SQLIntegrityConstraintViolationException;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
public class FlowableWorkflowServiceImpl implements WorkflowService {

    private static final Logger logger = LoggerFactory.getLogger(FlowableWorkflowServiceImpl.class);

    //Group的id格式应为 tenantId_groupId
    @Override
    public void addUserToGroup(String userId, String groupId, String tenantId) {
        ProcessEngine engine = FlowableConfig.getProcessEngine();
        IdentityService identityService = engine.getIdentityService();

        //TODO 改为用户不存在则创建 最好加锁保证并发安全
        String reallyGroupId = tenantId + "_" + groupId;
        Group group = identityService.createGroupQuery()
                .groupId(reallyGroupId)
                .singleResult();
        if (Objects.isNull(group)) {
            group = identityService.newGroup(reallyGroupId);
            identityService.saveGroup(group);
        }

        try {
            identityService.createMembership(userId, reallyGroupId);
        } catch (Exception e) {
            logger.error("创建用户于用户组关联关系出错了:",e);
        }

    }

    @Override
    public void createUser(String userId, String tenantId) {
        ProcessEngine engine = FlowableConfig.getProcessEngine();
        IdentityService identityService = engine.getIdentityService();

        User user = identityService.createUserQuery()
                .userId(userId)
                .tenantId(tenantId)
                .singleResult();
        if (Objects.isNull(user)) {
            user = identityService.newUser(userId);
            user.setTenantId(tenantId);
            identityService.saveUser(user);
        }
    }

    @Override
    public void deploy(String tenantId, String resourcePath) {

        ProcessEngine engine = FlowableConfig.getProcessEngine();
        RepositoryService repositoryService = engine.getRepositoryService();
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource(resourcePath)
                .tenantId(tenantId)
                .deploy();

        //key为业务中定义的有业务意义的一个标识符
        logger.info("the deployed businessKey is : {}", deploy.getKey());
    }

    //key对应xml中的process id
    @Override
    public String startProcessInstance(String key, String tenantId, Map<String, Object> variables) {
        ProcessEngine engine = FlowableConfig.getProcessEngine();
        RuntimeService runtimeService = engine.getRuntimeService();
        ProcessInstance processInstance = null;
        // 设置当前用户为 "xyf"
        String startUserId = variables.get("initiator").toString();
        engine.getIdentityService().setAuthenticatedUserId(startUserId);//不设置表 ACT_HI_PROCINST 中的 START_USER_ID就会为空
        if (Objects.isNull(variables) || variables.isEmpty()) {
            processInstance = runtimeService.startProcessInstanceByKeyAndTenantId(key, tenantId);
        } else {
            processInstance = runtimeService.startProcessInstanceByKeyAndTenantId(key, variables, tenantId);
        }
        logger.info("start processInstance succeed; the definitionId is : {} ", processInstance.getProcessDefinitionId());
        return processInstance.getId();
    }

    @Override
    public List<Task> queryUserActiveTask(String userId, String tenantId) {
        ProcessEngine engine = FlowableConfig.getProcessEngine();
        TaskService taskService = engine.getTaskService();
        List<Task> list = taskService.createTaskQuery()
                .active()
                .taskCandidateOrAssigned(userId)
                .taskTenantId(tenantId)
                .list();
        logger.info("the task list of {} are : {}", userId, list);
        return list;
    }

    @Override
    public void submitUserTask(String taskId, String userId, Map<String, Object> data) {


        ProcessEngine engine = FlowableConfig.getProcessEngine();
        TaskService taskService = engine.getTaskService();

        //认领任务
        taskService.claim(taskId, userId);

        //完成任务
        taskService.complete(taskId, data);

    }

    @Override
    public List<HistoricProcessInstance> getApprovedHistory(String userId,String tenantId) {
        ProcessEngine engine = FlowableConfig.getProcessEngine();
        HistoryService historyService = engine.getHistoryService();

        return historyService.createHistoricProcessInstanceQuery()
                .processInstanceTenantId(tenantId)
                .startedBy(userId)
                .finished()
                .orderByProcessInstanceEndTime()
                .desc()
                .list();
    }
}
